#ifndef SIMPLE_ANIM
#define SIMPLE_ANIM

#include "../../common/stdafx.h"

//-----------------------------------------------------
// File:    CSimpleAnimator.h
// Created: 05/17/2012
// Editted:     ""
// Change:  Creation
// Author:  Stephen J Edwards
//-----------------------------------------------------
// Purpose: Implement simple functions and data
//          for All animations that will be used
//          in the engine.
//-----------------------------------------------------

enum AnimationType {DEFAULT_ANIM = 0, BACKGROUND_ANIM, SPRITE_ANIM, PARTICLE_ANIM, EFFECT_ANIM, MAX_ANIMS};

//-------------------------------------------------------------
// Purpose: Stores the data for a single animation frame
//-------------------------------------------------------------
struct Frame
{
    // TODO: convert to a math rectangle
    int mapPosition[2];     // The x and y location of the top left corner of the bounds on the animation bitmap
    int boundBox[2];        // Represents the bounding box around the animation, length and width
    int anchorPoint[2];     // This point will always line up on every frame, it is relative to the top left corner of the bound
    float keyTime;          // The time This frame should occur at during the animation, if this is -1.0 the default framerate will be used
}

//-------------------------------------------------------------
// Purpose: Stores and controls the data for a basic animation
//-------------------------------------------------------------
class CAnimation
{
private:
    float   animationDuration;    // length of time the animation takes to finish one cycle
    float   currentTime;        // the time we are currently playing at
    int     numberOfFrames;     // total frames used to complete the animation in one cycle
    int     animationType;      // This is based on the AnimationType enumeration
    int     currentFrame;       // the frame we are currently showing
    bool    isLooping;          // controls the animation loop/continuous play, default is false
    bool    isReverse;          // play animation backwards, default is false
    // ?TODO?: Migrate this option up the chain so that it is controlled by the system, not an individual animation
    bool    allowFrameskip;     // Allow the game to skip over a frame, default is false
    
    std::vector<Frame>  animationFrames;    // The frames belonging to this animation
    
    std::string bitmapFilename;     // The filename of the bitmap we're using, used for rendering

public:

    CAnimation ()
    {
        animationDuration = 2.0f;
        currentTime = 0.0f;
        numberOfFrames = 6;
        animationType = DEFAULT_ANIM;
        currentFrame = 0;
        isLooping = false;
        isReverse = false;
        allowFrameskip = false;
    }

     // Mutators
    void SetLoop (bool loop) {isLooping = loop;}
    void SetCurrentFrame (int curr) {currentFrame = curr;}
    void SetType (int animType) {animationType = animType;}

    // Accessors
    bool GetLoop () {return isLooping;}
    bool GetReverse () {return isReverse;}
    bool GetFrameskip () {return allowFrameskip;}
    Frame GetFrame (int frameNumber) {return animationFrames[frameNumber];}
    Frame GetCurrentFrame () {return animationFrames[currentFrame];}
    float GetFrameKey (int frameNumber) 
    { 
        if(GetFrame(frameNumber).keyTime == -1) 
            return (0.2f * frameNumber);
        else
            return GetFrame(frameNumber).keyTime;
    }

    // TODO: Future implementation of loaded animations using binary files created in an external tool
    // Loads an animation from a binary file containing generic information
    void LoadAnimation (std::string filename) {}

    // TODO: makes a default test animation using the given bitmap
    // Default Settings: 4 frames, 64x80 pixels each, 0.5 seconds between frames, 2 second total time, looping is true, type is DEFAULT_ANIM
    void createDefaultAnimation (std::string bitmap) {}

    // Controls Moving between frames and updating an animation. The animator should only have to call addTime on an animation to update it.
    // ?TODO?: rename this function to "update" since it does more than just adding time.
    void AddTime (float delta)  
    {
        do
        {
            if(!isReverse)
            {
                if(!isLooping)
                {
                    // this animation is playing forward and stops at the last frame
                    if(currentTime + delta >= GetFrameKey(currentFrame + 1) && currentFrame < numberOfFrames - 1)
                        currentFrame++;
                    else
                        break;
                }
                else
                {
                    // this animation is playing forwards and looping
                    if(currentFrame == numberOfFrames - 1 && currentTime + delta >= animationDuration)
                    {
                        currentFrame = 0;
                        // take off the amount of time we moved from delta and reset currentTime
                        delta -= animationDuration - currentTime;
                        currentTime = 0.0f;
                    }
                    else if(currentTime + delta >= GetFrameKey(currentFrame + 1))
                        currentFrame++;
                    else
                        break;
                }
            }
            else
            {
                if(!isLooping)
                {
                    // The animation is in reverse, but not looping
                    if(currentTime - delta < GetFrameKey(currentFrame) && currentFrame > 0)
                        currentFrame--;
                    else
                        break;
                }
                else
                {
                    // the animation is reversed and looping
                    if(currentFrame == 0 && currentTime - delta < 0.0f)
                    {
                        currentFrame = numberOfFrames -1;
                        delta -= currentTime;
                        currentTime = animationDuration;
                    }
                    else if(currentTime - delta < GetFrameKey(currentFrame))
                        currentFrame--;
                    else
                        break;
                }
            }
        } while(allowFrameskip);
    }
};

//-----------------------------------------------------------------
// Purpose: Holds the active animations and controls their update
//-----------------------------------------------------------------
class CSimpleAnimator
{
private:
    std::vector<CAnimation>     activeAnimations;
    // TODO: add in animator memory manager or functionality for dynamically adding and pulling animations

public:
    CSimpleAnimator() {}

    // TODO: Write Definition in .cpp
    void Update (float delta)
    {
        for(int currentAnim = 0; currentAnim < activeAnimations.size(); currentAnim++)
        {
            activeAnimations[currentAnim].AddTime(delta);           
        }
    }
    

};

#endif